package uk.ac.open.kmi.dyniqx.repositories;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.document.Field;
import org.directwebremoting.WebContext;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

import uk.ac.open.kmi.dyniqx.storages.Storage;

public class PerXThread extends Thread {
	
	public String queryString;
	public String queryID;
	public String databaseID;
	public int databaseCount;
	
	public Storage storage;
	public WebContext wctx;
	
	public volatile boolean stop = false;
	
	public Logger logger = Logger.getLogger("uk.ac.open.kmi.dyniqx.repositories.PerXThread");
	
	public PerXThread(Storage storage, WebContext wctx, String queryString, String queryID, String databaseID, int databaseCount) {
		
		this.setStorage(storage);
		this.setWctx(wctx);
		this.setQueryString(queryString);
		this.setQueryID(queryID);
		this.setDatabaseID(databaseID);
		this.setDatabaseCount(databaseCount);
		
	}
	
	@SuppressWarnings("unchecked")
	public void run() {
		
		this.logger.debug("Thread started.");
		
		SAXBuilder parser = new SAXBuilder();
		String searchUrl = "http://www.engineering.ac.uk/sru/?operation=searchRetrieve&version=1.1&x-queryID=" + this.getQueryID() + "&x-databaseID=" + this.getDatabaseID() + "&query=" + this.getQueryString();
		if (this.getDatabaseCount() > 100) this.setDatabaseCount(100);
		int startIndex = 1;
		int max = 10;
		int temp_count = 0;
		Document doc;
		
		/* Open University proxy Settings */
		 
		System.getProperties().put( "proxySet", "true" );
		System.getProperties().put( "proxyHost", "wwwcache" );
		System.getProperties().put( "proxyPort", "80" );
		System.setProperty("java.net.useSystemProxies","true");
		
		try {
			
			while ((startIndex <= this.getDatabaseCount()) && !stop) {
				
				doc = parser.build(searchUrl + "&maximumRecords=" + max + "&startRecord=" + startIndex);
								
				List<Element> list = (List<Element>) XPath.newInstance("/zs:searchRetrieveResponse/zs:record/zs:recordData").selectNodes(doc);
			    Iterator iterator = list.iterator();
			    
			    org.apache.lucene.document.Document result = null;
			    ArrayList<org.apache.lucene.document.Document> documentArray = new ArrayList<org.apache.lucene.document.Document>();
			    
			    while (iterator.hasNext()) {
			        Element el = (Element) iterator.next();
			        el = (Element) el.getChildren().get(0);
			        			        
			        String id = XPath.newInstance("dc:identifier").valueOf(el);
			        String title = XPath.newInstance("dc:title").valueOf(el);
			        String description = XPath.newInstance("dc:description").valueOf(el);
			        String link = XPath.newInstance("dc:identifier").valueOf(el);
			        String internal = XPath.newInstance("dc:identifier").valueOf(el);
			        
			        String authors = XPath.newInstance("dc:creator").valueOf(el);
			        String date = XPath.newInstance("dc:date").valueOf(el);
			        String journal = XPath.newInstance("dc:publisher").valueOf(el);
			        
			        result = new org.apache.lucene.document.Document();

			        result.add(new Field("source", "PrX", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("type", "text", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("id", id, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("query", queryString, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("rank", Integer.toString(++temp_count), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        			        
			        result.add(new Field("link", link, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("internal", internal, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("title", title, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES));
			        result.add(new Field("description", description, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES));
			        
			        result.add(new Field("date", date, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("authors", authors, Field.Store.YES, Field.Index.TOKENIZED));
			        result.add(new Field("journal", journal, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        
			        result.add(new Field("summary", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("width", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("height", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("fileSize", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("fileFormat", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbUrl", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbWidth", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbHeight", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        
			        result.setBoost(100 / temp_count);
			        
			        documentArray.add(result);
			    }
			    
			    this.storage.performIOAction(Storage.WRITE_ACTION, documentArray);
			    this.storage.updateGrid();

			    startIndex += max;
			}
		    
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}		

		if (this.stop) {
			this.logger.debug("Thread killed.");
            return;
        }
		
		this.logger.debug("Thread ended.");
    }
	
	public void setQueryString(String queryString) {
		this.queryString = queryString;
	}
	
	public String getQueryString() {
		return this.queryString;
	}
	
	public void setStorage(Storage storage) {
		this.storage = storage;
	}	
	
	public Storage getStorage() {
		return this.storage;
	}

	public WebContext getWctx() {
		return wctx;
	}

	public void setWctx(WebContext wctx) {
		this.wctx = wctx;
	}

	public String getQueryID() {
		return queryID;
	}

	public void setQueryID(String queryID) {
		this.queryID = queryID;
	}

	public String getDatabaseID() {
		return databaseID;
	}

	public void setDatabaseID(String databaseID) {
		this.databaseID = databaseID;
	}

	public int getDatabaseCount() {
		return databaseCount;
	}

	public void setDatabaseCount(int databaseCount) {
		this.databaseCount = databaseCount;
	}
}
